/*****************************************************************************
*                     Organizacion de Datos - 75.06                          *
*                         Catedra Lic. Servetto                              *
*            Facultad de Ingenieria - Universidad de Buenos Aires            *
******************************************************************************/ 

#include "../Comun/ConversorDeStreams.h"

#include "ConexionCapaFisica.h"

#include <string>
#include <iostream>
#include <fstream>
#include <sstream>

#ifdef WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif

using namespace std;
using namespace Comun;

namespace CapaIndices
{

	static int contadorOperaciones = 0;

	void ConexionCapaFisica::GenerarLlamada(stringstream* entrada, stringstream* salida)
	{
		if (contadorOperaciones < 0)
			contadorOperaciones = 0;

		stringstream* s = new stringstream();
		*s << "Transacciones/CapaFisica/Entrada/" << contadorOperaciones << ".txt";

		ofstream archivoEntrada(s->str().c_str());
		archivoEntrada << salida->rdbuf();
		archivoEntrada.close();

#ifdef WIN32

		s = new stringstream();
		*s << "CapaFisica.EXE " << contadorOperaciones;

		system(s->str().c_str());		

#else

		s = new stringstream();
		*s << "./CapaFisica " << contadorOperaciones;

		system(s->str().c_str());		

#endif

		s = new stringstream();
		*s << "Transacciones/CapaFisica/Salida/" << contadorOperaciones << ".txt";

		ifstream* archivoSalida = new ifstream();

		archivoSalida->open(s->str().c_str());

		(*entrada) << archivoSalida->rdbuf();

		archivoSalida->close();
		delete archivoSalida;

		contadorOperaciones++;
	};

	bool ConexionCapaFisica::ExisteClase(string clase)
	{
		stringstream* entrada = new stringstream();
		stringstream* salida = new stringstream();

		ConversorDeStreams::OperacionAStream( Comun::ExisteClase, salida );
		ConversorDeStreams::CadenaAStream( clase, salida );

		GenerarLlamada(entrada, salida);

		return ConversorDeStreams::StreamABooleano(entrada);
	};

	void ConexionCapaFisica::CrearArchivoRF(MetadatosArchivo& metadatosDelArchivo)
	{
		stringstream* entrada = new stringstream();
		stringstream* salida = new stringstream();

		ConversorDeStreams::OperacionAStream( Comun::CrearArchivoRF, salida );
		ConversorDeStreams::MetadatosDeArchivoAStream( metadatosDelArchivo, salida );

		GenerarLlamada(entrada, salida);
	};

	void ConexionCapaFisica::CrearArchivoRLV(MetadatosArchivo& metadatosDelArchivo)
	{
		stringstream* entrada = new stringstream();
		stringstream* salida = new stringstream();

		ConversorDeStreams::OperacionAStream( Comun::CrearArchivoRLV, salida );
		ConversorDeStreams::MetadatosDeArchivoAStream( metadatosDelArchivo, salida );

		GenerarLlamada(entrada, salida);
	};

	int ConexionCapaFisica::CrearGrupo(string clase, Grupo& grupo)
	{
		stringstream* entrada = new stringstream();
		stringstream* salida = new stringstream();

		ConversorDeStreams::OperacionAStream( Comun::CrearGrupo, salida );
		ConversorDeStreams::DatosDeGrupoAStream( grupo, salida );
		ConversorDeStreams::CadenaAStream( clase, salida );

		GenerarLlamada(entrada, salida);

		return ConversorDeStreams::StreamAEntero(entrada);
	};

	CodigoResultado ConexionCapaFisica::GuardarGrupo(string clase, Grupo& grupo, bool omitirSubflujo)
	{
		stringstream* entrada = new stringstream();
		stringstream* salida = new stringstream();

		ConversorDeStreams::OperacionAStream( Comun::GuardarGrupo, salida );
		ConversorDeStreams::DatosDeGrupoAStream( grupo, salida );
		ConversorDeStreams::CadenaAStream( clase, salida );
		ConversorDeStreams::BooleanoAStream( omitirSubflujo, salida );

		GenerarLlamada(entrada, salida);

		int resultado = ConversorDeStreams::StreamAEntero(entrada);

		for(IteradorDeRegistros i = grupo.Registros.begin(); i != grupo.Registros.end(); ++i)
			(*i).Tamanio = ConversorDeStreams::StreamAEntero(entrada);

		return (CodigoResultado) resultado;
	};

	Grupo& ConexionCapaFisica::LeerGrupo(string clase, int grupoId)
	{
		stringstream* entrada = new stringstream();
		stringstream* salida = new stringstream();

		ConversorDeStreams::OperacionAStream( Comun::LeerGrupo, salida );
		ConversorDeStreams::EnteroAStream( grupoId, salida );
		ConversorDeStreams::CadenaAStream( clase, salida );

		GenerarLlamada(entrada, salida);

		return ConversorDeStreams::StreamADatosDeGrupo(entrada);
	};

	void ConexionCapaFisica::BorrarGrupo(string clase, int grupoId)
	{
		stringstream* entrada = new stringstream();
		stringstream* salida = new stringstream();

		ConversorDeStreams::OperacionAStream( Comun::BorrarGrupo, salida );		
		ConversorDeStreams::EnteroAStream( grupoId, salida );
		ConversorDeStreams::CadenaAStream( clase, salida );

		GenerarLlamada(entrada, salida);
	};

	int ConexionCapaFisica::PrimerGrupo(string clase)
	{
		stringstream* entrada = new stringstream();
		stringstream* salida = new stringstream();

		ConversorDeStreams::OperacionAStream( Comun::PrimerGrupo, salida );
		ConversorDeStreams::CadenaAStream( clase, salida );

		GenerarLlamada(entrada, salida);

		return ConversorDeStreams::StreamAEntero(entrada);
	};

	int ConexionCapaFisica::SiguienteGrupo(string clase, int grupoIdActual)
	{
		stringstream* entrada = new stringstream();
		stringstream* salida = new stringstream();

		ConversorDeStreams::OperacionAStream( Comun::SiguienteGrupo, salida );
		ConversorDeStreams::EnteroAStream( grupoIdActual, salida );
		ConversorDeStreams::CadenaAStream( clase, salida );

		GenerarLlamada(entrada, salida);

		return ConversorDeStreams::StreamAEntero(entrada);
	};

}
